//
//  YWDownloadDataTaskStatus.m
//  videoTest3
//
//  Created by jun peng on 2022/7/23.
//

#import "YWDownloadDataTaskStatus.h"

@interface YWDownloadDataTaskStatus ()<NSURLSessionDataDelegate>

//由status里面属性fullPath产生、不需要保存到本地
@property (nonatomic, strong) NSFileHandle *handle;

//当你进入下载页面、传入status进来我就创建一个由新的session创建一个新的任务
@property (nonatomic, strong)  NSURLSessionDataTask *dataTask;

@property (nonatomic, strong) NSURLSession *session;
@property (nonatomic,strong)NSTimer *timer;

@end

@implementation YWDownloadDataTaskStatus


//添加定时器
-(void)addTimer{
    
    //先发一次通知再开定时
    [self sendProgressNotification];
    
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(sendProgressNotification) userInfo:nil repeats:YES];
    
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    self.timer = timer;
}

//移除定时器
-(void)removeTimer{
    
    [self.timer invalidate];
    
    self.timer = nil;
    
}

//发送进度通知
-(void)sendProgressNotification{
    
    //发送通知
    NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
    [[NSNotificationCenter defaultCenter] postNotificationName:YWProgressDownloadNote object:self userInfo:userInfo];
}

-(NSURLSession *)session
{
    if (_session == nil) {
        //3.创建会话对象,设置代理
        /*
         第一个参数:配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
         第二个参数:代理
         第三个参数:设置代理方法在哪个线程中调用
         */
        _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _session;
}

-(NSURLSessionDataTask *)dataTask
{
    if (_dataTask == nil) {
        //1.url
        NSURL *url = [NSURL URLWithString:self.status.VideoUrl];
        
        //2.创建请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        
        YWLog(@"self.status.fullPath：%@",self.status.fullPath);
        
        //3 设置请求头信息,告诉服务器请求那一部分数据
        self.status.currentSize = [self getFileSizeWithFullPath:self.status.fullPath];
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.status.currentSize];
        [request setValue:range forHTTPHeaderField:@"Range"];
        
        //4.创建Task
        _dataTask = [self.session dataTaskWithRequest:request];
    }
    return _dataTask;
}

//创建了任务
-(void)createDataTask{
   
    [self removeTimer];
    
    [self.dataTask resume];
    
    self.status.downloadType = YWDownloadType_Downloading;
    
    //发送通知
    NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
//    [[NSNotificationCenter defaultCenter] postNotificationName:YWResumeDownloadNote object:self userInfo:userInfo];
    
    [self addTimer];
}

//继续任务
-(void)continueDataTask{
    
    [self removeTimer];
    
    [self.dataTask resume];
    
    self.status.downloadType = YWDownloadType_Downloading;
    
    //发送通知
    NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
//    [[NSNotificationCenter defaultCenter] postNotificationName:YWResumeDownloadNote object:self userInfo:userInfo];
    
    [self addTimer];
}

//暂停任务
-(void)pauseDataTask{
    
    [self removeTimer];
    
    [self.dataTask suspend];
    
    self.status.downloadType = YWDownloadType_Pause;
    
    
    //发送通知
    NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
//    [[NSNotificationCenter defaultCenter] postNotificationName:YWPauseDownloadNote object:self userInfo:userInfo];
}



//删除了任务
-(void)removeDataTask{
    
    [self removeTimer];
    
    [self.dataTask cancel];
    self.dataTask = nil;
    
    
    self.status.downloadType = YWDownloadType_Remove;
    
    //移除文件
    NSError *error2 = nil;
    if ([[NSFileManager defaultManager] fileExistsAtPath:self.status.fullPath]) {
         [[NSFileManager defaultManager] removeItemAtPath:self.status.fullPath error:&error2];
        if (error2 == nil) {
            YWLog(@"移除无效视频文件成功");
        }
        else{
            YWLog(@"移除无效视频文件失败");
        }
    }
    
    
    //发送通知
    NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
//    [[NSNotificationCenter defaultCenter] postNotificationName:YWRemoveDownloadNote object:self userInfo:userInfo];
    
}

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////


#pragma mark ----------------------
#pragma mark NSURLSessionDataDelegate
/**
 *  1.接收到服务器的响应 它默认会取消该请求
 *
 *  @param session           会话对象
 *  @param dataTask          请求任务
 *  @param response          响应头信息
 *  @param completionHandler 回调 传给系统
 */
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
    
    NSURL *url = response.URL;
    
    NSLog(@"url:%@",url);
    
    //获得文件的总大小
    //expectedContentLength 本次请求的数据大小
    //这里设置totalSize、currentSize在发起开启下载的时候已经设置过这里不需要重复设置了
    self.status.totalSize = response.expectedContentLength + self.status.currentSize;
   
    
    //假如currentSize是零即一点数据根本不存在都没有就要创建一个文件了
    if (self.status.currentSize == 0) {
        //创建空的文件
        [[NSFileManager defaultManager]createFileAtPath:self.status.fullPath contents:nil attributes:nil];
        
    }
    
    //创建文件句柄
    self.handle = [NSFileHandle fileHandleForWritingAtPath:self.status.fullPath];
    
    //移动指针
    [self.handle seekToEndOfFile];
    
    
    //发送通知
    NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
    [[NSNotificationCenter defaultCenter] postNotificationName:YWStartDownloadNote object:self userInfo:userInfo];
    
    /*
     NSURLSessionResponseCancel = 0,取消 默认
     NSURLSessionResponseAllow = 1, 接收
     NSURLSessionResponseBecomeDownload = 2, 变成下载任务
     NSURLSessionResponseBecomeStream        变成流
     */
    completionHandler(NSURLSessionResponseAllow);
    
}

/**
 *  接收到服务器返回的数据 调用多次
 *
 *  @param session           会话对象
 *  @param dataTask          请求任务
 *  @param data              本次下载的数据
 */
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    
    //移动指针(上面写了，这里可以不写，它writeData就是默认追加到后面)
//    [self.handle seekToEndOfFile];
    
    //写入数据到文件
    [self.handle writeData:data];
    
    //计算文件的下载进度
//    self.status.currentSize += data.length;
    
    //不用上面的、用这个根据fullPath获取更合理更准确
    self.status.currentSize = [self getFileSizeWithFullPath:self.status.fullPath];
    NSLog(@"%f",1.0 * self.status.currentSize / self.status.totalSize);
    
    
    
    NSArray *downloadinigStatusArray = [NSKeyedUnarchiver unarchiveObjectWithFile:YWDownloadingStatuspath];
    
    NSMutableArray *mDownloadinigStatusArray = [NSMutableArray arrayWithArray:downloadinigStatusArray];
    
    //倒叙删除正在下载数组的元素
     [mDownloadinigStatusArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
         
         YWDownloadStatus *downloadStatus = (YWDownloadStatus *)obj;

         if ([downloadStatus.VideoUrl isEqualToString:self.status.VideoUrl]){

             downloadStatus.currentSize = self.status.currentSize;
//             [mDownloadinigStatusArray removeObject:downloadStatus];
             *stop = YES;

         }
     }];
    
    
    //归档到到完成数据
//    [mDownloadinigStatusArray addObject:self.status];

    
    downloadinigStatusArray = mDownloadinigStatusArray;
    
    // 归档模型（保存到本地）
    [NSKeyedArchiver archiveRootObject:downloadinigStatusArray toFile:YWDownloadingStatuspath];
        
    
}

/**
 *  请求结束或者是失败的时候调用
 *
 *  @param session           会话对象
 *  @param dataTask          请求任务
 *  @param error             错误信息
 */
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    [self removeTimer];
    
    NSLog(@"%@",self.status.fullPath);
    
    //关闭文件句柄
    [self.handle closeFile];
    self.handle = nil;
    
    
    if (error == nil) {
        
        //1、改枚举状态
        self.status.downloadType = YWDownloadType_Finish;
        
        //2、改路径
        self.status.fullPath = [self moveFileToFinishPahFromDownloadingPah:self.status.fullPath];
        
        //3、发送通知
        NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
        [[NSNotificationCenter defaultCenter] postNotificationName:YWFinishDownloadNote object:self userInfo:userInfo];
    }
    else{
        
        //1、改枚举状态
        self.status.downloadType = YWDownloadType_Error;
        
        //2、发送通知
        NSDictionary *userInfo = @{YWDownloadStatusKey:self.status};
        [[NSNotificationCenter defaultCenter] postNotificationName:YWErrorDownloadNote object:self userInfo:userInfo];

    }
    
    
}

-(void)dealloc
{
    [self removeTimer];
    
    //清理工作
    //finishTasksAndInvalidate
    [self.session invalidateAndCancel];
}



//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

//创建完成下载文件夹
-(NSString *)createFinishDowloadFolder{
    
    NSError *error = nil;
    if (![[NSFileManager defaultManager] fileExistsAtPath:YWFinishDownloadCachepath]) {
         [[NSFileManager defaultManager] createDirectoryAtPath:YWFinishDownloadCachepath
                                   withIntermediateDirectories:NO
                                                    attributes:nil
                                                         error:&error];
    }
    return YWFinishDownloadCachepath;
}


//从正在下载文件夹移动文件到完成下载的文件夹,从而获得新的移动路径
-(NSString *)moveFileToFinishPahFromDownloadingPah:(NSString *)downloadingPahfromPath{
    NSFileManager *fileManager = [NSFileManager defaultManager];
   
    NSString *lastConponent = [downloadingPahfromPath lastPathComponent];
    
    NSString *path = [[self createFinishDowloadFolder] stringByAppendingPathComponent:lastConponent];
    
    //视频存放到这个位置
    NSError *error = nil;
    [fileManager moveItemAtURL:[NSURL fileURLWithPath:downloadingPahfromPath] toURL:[NSURL fileURLWithPath:path] error:&error];
    if (error == nil) {
        YWLog(@"移动成功");
    }
    else{
        YWLog(@"移动失败");
    }
    
    return path;
}


//传入本地路径获取文件大小
-(NSInteger)getFileSizeWithFullPath:(NSString *)fullPath{
    
    //获得指定文件路径对应文件的数据大小
    NSDictionary *fileInfoDict = [[NSFileManager defaultManager]attributesOfItemAtPath:fullPath error:nil];
    
    NSLog(@"fullPath: %@",fullPath);
    
    NSLog(@"%@",fileInfoDict);
    NSInteger currentSize = [fileInfoDict[@"NSFileSize"] integerValue];
    
    return currentSize;
}




@end
